package com.yeskery.nut.core;

import com.yeskery.nut.util.ReflectUtils;

import java.io.Console;
import java.lang.invoke.MethodHandles;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * Java版本
 * @author YESKERY
 * 2023/9/8
 */
public enum JavaVersion {


    /**
     * Java 1.8.
     */
    EIGHT("1.8", Optional.class, "empty"),

    /**
     * Java 9.
     */
    NINE("9", Optional.class, "stream"),

    /**
     * Java 10.
     */
    TEN("10", Optional.class, "orElseThrow"),

    /**
     * Java 11.
     */
    ELEVEN("11", String.class, "strip"),

    /**
     * Java 12.
     */
    TWELVE("12", String.class, "describeConstable"),

    /**
     * Java 13.
     */
    THIRTEEN("13", String.class, "stripIndent"),

    /**
     * Java 14.
     */
    FOURTEEN("14", MethodHandles.Lookup.class, "hasFullPrivilegeAccess"),

    /**
     * Java 15.
     */
    FIFTEEN("15", CharSequence.class, "isEmpty"),

    /**
     * Java 16.
     */
    SIXTEEN("16", Stream.class, "toList"),

    /**
     * Java 17.
     */
    SEVENTEEN("17", Console.class, "charset"),

    /**
     * Java 18.
     */
    EIGHTEEN("18", Duration.class, "isPositive");

    /** java版本名称 */
    private final String name;

    /** 是否有效 */
    private final boolean available;

    /**
     * 构建Java版本
     * @param name java版本名称
     * @param clazz 要判断的类名
     * @param methodName 要判断的方法名
     */
    JavaVersion(String name, Class<?> clazz, String methodName) {
        this.name = name;
        this.available = ReflectUtils.existMethod(clazz, methodName);
    }

    @Override
    public String toString() {
        return this.name;
    }

    /**
     * 获取Java版本
     * @return Java版本
     */
    public static JavaVersion getJavaVersion() {
        List<JavaVersion> candidates = Arrays.asList(JavaVersion.values());
        Collections.reverse(candidates);
        for (JavaVersion candidate : candidates) {
            if (candidate.available) {
                return candidate;
            }
        }
        return EIGHT;
    }

    /**
     * 判断是否比指定版本相等或更高
     * @param version 指定版本
     * @return 是否比指定版本相等或更高
     */
    public boolean isEqualOrNewerThan(JavaVersion version) {
        return compareTo(version) >= 0;
    }

    /**
     * 判断是否比指定版本低
     * @param version 指定版本
     * @return 是否比指定版本低
     */
    public boolean isOlderThan(JavaVersion version) {
        return compareTo(version) < 0;
    }
}
